using Cysharp.Threading.Tasks;
using LFrameworkAOT;
using System;
using UnityEngine;
using YooAsset;

namespace LFramework
{
    public class AssetRefEntity
    {
        /// <summary>
        /// 资源完整路径，包含后缀名
        /// </summary>
        public string AssetFullPath;

        /// <summary>
        /// 资源释放时间
        /// </summary>
        public float ReleaseTime { get; private set; }

        /// <summary>
        /// 引用计数
        /// </summary>
        public int ReferenceCount { get; private set; }

        /// <summary>
        /// 加载asset 的句柄
        /// </summary>
        public AssetHandle AssetHandler { get; private set; }

        /// <summary>
        /// 加载完成回调
        /// </summary>
        private Action<string,UnityEngine.Object> m_LoadCompleteCB;

        /// <summary>
        /// 刷新最后使用时间
        /// </summary>
        public void RefreshReleaseTime()
        {
            ReleaseTime = Time.time + GameLaunch.ParamsSettings.PoolReleaseAssetInterval;
        }

        /// <summary>
        /// 引用计数+1
        /// </summary>
        public void ReferenceAdd()
        {
            ReferenceCount++;
        }

        /// <summary>
        /// 引用计数-1
        /// </summary>
        public void ReferenceRemove()
        {
            ReferenceCount--;
            if (ReferenceCount == 0)
                RefreshReleaseTime();

            if (ReferenceCount < 0)
            {
                GameEntry.LogError("Asset引用计数出错， ReferenceCount==" + ReferenceCount);
            }
        }

        /// <summary>
        /// 对象是否可以释放
        /// </summary>
        /// <returns></returns>
        public bool GetCanRelease()
        {
            return ReferenceCount == 0 && Time.time >= ReleaseTime;
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Release()
        {
            AssetFullPath = null;
            AssetHandler.Release();
            AssetHandler = null;
            m_LoadCompleteCB = null;
            GameEntry.Pool.ClassObjectPool.Enqueue(this);
        }

        public static AssetRefEntity Create(string assetFullPath)
        {
            AssetRefEntity referenceEntity = GameEntry.Pool.ClassObjectPool.Dequeue<AssetRefEntity>();
            referenceEntity.AssetFullPath = assetFullPath;

            return referenceEntity;
        }

        /// <summary>
        /// 异步加载回调方式
        /// </summary>
        public void LoadAssetAsync(Action<string,UnityEngine.Object> loadCompleteCB)
        {
            if (AssetHandler == null) 
            {
                AssetHandler = YooAssets.LoadAssetAsync(AssetFullPath);
                AssetHandler.Completed += Completed;
            }
            if (AssetHandler.AssetObject != null)
                loadCompleteCB?.Invoke(AssetFullPath,AssetHandler.AssetObject);
            else
                m_LoadCompleteCB += loadCompleteCB;
        }

        //异步回调
        private void Completed(AssetHandle assetHandle) 
        {
            if (AssetHandler.Status == EOperationStatus.Succeed)
            {
                m_LoadCompleteCB?.Invoke(AssetFullPath,assetHandle.AssetObject);
            }
            else
                GameEntry.Log("加载资源失败");
            m_LoadCompleteCB = null;
        }

        /// <summary>
        /// 异步卸载
        /// </summary>
        /// <param name="loadCompleteCB"></param>
        public void UnloadAssetAsync(Action<string,UnityEngine.Object> loadCompleteCB) 
        {
            m_LoadCompleteCB -= loadCompleteCB;
        }

        /// <summary>
        /// 异步加载
        /// </summary>
        public async UniTask<T> LoadAssetAsync<T>() where T : UnityEngine.Object
        {
            if(AssetHandler == null)
                AssetHandler = YooAssets.LoadAssetAsync<T>(AssetFullPath);
            await AssetHandler.ToUniTask();

            return AssetHandler.AssetObject as T;
        }

        /// <summary>
        /// 同步加载
        /// </summary>
        public T LoadAssetSync<T>() where T : UnityEngine.Object
        {
            if (AssetHandler == null)
                AssetHandler = YooAssets.LoadAssetSync<T>(AssetFullPath);
            return AssetHandler.AssetObject as T;
        }
    }
}
